package com.towexin.application.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.towexin.application.system.domain.Authority;
import com.towexin.application.system.domain.RoleAuthority;
import com.towexin.application.system.mapper.AuthorityMapper;
import com.towexin.application.system.service.AuthorityMenuService;
import com.towexin.application.system.service.AuthorityService;
import com.towexin.application.system.service.RoleAuthorityService;
import com.towexin.application.system.service.RoleService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TODO
 *
 * @author Towexin
 * @version 1.0
 * @date 2021/4/12 18:27
 */
@Service
@Transactional
public class AuthorityServiceImpl extends ServiceImpl<AuthorityMapper, Authority> implements AuthorityService {
	@Autowired
	private AuthorityMenuService authorityMenuService;

	@Autowired
	private RoleAuthorityService roleAuthorityService;

	@Autowired
	private RoleService roleService;

	// 添加或更新权限信息
	@Override
	public boolean saveOrUpdateAuthority(Authority authority) {
		authority.setOpen(true);
		if (saveOrUpdate(authority)) {
			List<String> roleIds = roleService
					.getParentIdsByUserName(SecurityUtils.getSubject().getPrincipal().toString());

			List<RoleAuthority> roleAuthorities = new ArrayList<>();
			for (String roleId : roleIds) {
				RoleAuthority roleAuthority = new RoleAuthority();
				roleAuthority.setAId(authority.getId());
				roleAuthority.setRId(roleId);
				roleAuthorities.add(roleAuthority);
			}
			// 先删除再更新
			roleAuthorityService
					.remove(new QueryWrapper<RoleAuthority>().in("r_id", roleIds).eq("a_id", authority.getId()));
			return roleAuthorityService.saveBatch(roleAuthorities);
		}
		return false;
	}

	// 级联删除权限信息
	@Override
	public boolean deleteCascadeId(String id) {
		List<String> ids = getCascadeId(id, list());
		if (removeByIds(ids)) {
			authorityMenuService.removeByIds(ids);
			roleAuthorityService.remove(new QueryWrapper<RoleAuthority>().in("a_id", ids));
			return true;
		}
		return false;
	}

	// 获取权限列表 —— 树结构
	@Override
	public List<Map<String, Object>> selectAuthorityTree(boolean flag) {
		Subject subject = SecurityUtils.getSubject();
		if (flag) {
			// 添加权限时获取上级权限
			List<Map<String, Object>> mapList = new ArrayList<>();
			Map<String, Object> map = new HashMap<>();
			map.put("title", "根节点");
			map.put("id", "no");
			map.put("mark", "");
			map.put("children",
					authorityRecursion("no", baseMapper.selectAuthByUserName(subject.getPrincipal().toString()), true));
			mapList.add(map);
			return mapList;
		}
		return authorityRecursion("no", baseMapper.selectAuthByUserName(subject.getPrincipal().toString()), false);
	}

	// 获取权限列表
	@Override
	public List<Map<String, Object>> selectAllMap() {
		Subject subject = SecurityUtils.getSubject();
		return baseMapper.selectMapAllByUserName(subject.getPrincipal().toString());
	}

	// 获取权限父节点关联的菜单id
	@Override
	public String checkMenu(String pId) {
		if (!pId.equals("no")) {
			String menuId = baseMapper.checkMenu(pId);
			if (menuId == null || menuId.equals("")) {
				return "请先关联父节点";
			} else {
				return menuId;
			}
		}
		return "no";
	}

	// 获取权限列表 shiro 用
	@Override
	public List<Authority> selectByUserName(String userName) {
		return baseMapper.selectAuthByUserName(userName);
	}

	@Override
	public List<Authority> selectByRid(String rId) {
		return baseMapper.selectAuthByRid(rId);
	}

	/**
	 * 获取权限列表（包含默认角色权限，排除冻结角色）
	 * @param username
	 * @return
	 */
	@Override
	public List<String> selectMarkAndDefaultRoleByUserName(String username) {
		return baseMapper.selectMarksAndDefaultRoleByUserName(username);
	}

	// 权限递归树结构
	protected List<Map<String, Object>> authorityRecursion(String pId, List<Authority> authorities, boolean flag) {
		List<Map<String, Object>> mapList = new ArrayList<>();
		for (Authority authority : authorities) {
			// 获取权限父节点时排除按钮(最底层节点)
			if (flag && authority.getBtn()) {
				continue;
			}
			if (authority.getPid().equals(pId)) {
				Map<String, Object> map = new HashMap<>();
				if (flag) {
					map.put("title", authority.getAuthorityName());
				} else {
					map.put("title", authority.getAuthorityName() + "【" + authority.getAuthorityMark() + "】");
				}
				map.put("id", authority.getId());
				map.put("spread", "true");
				map.put("mark", authority.getAuthorityMark());
				map.put("children", authorityRecursion(authority.getId(), authorities, flag));
				mapList.add(map);
			}
		}
		return mapList;
	}

	// 获取级联id
	protected List<String> getCascadeId(String id, List<Authority> authorities) {
		List<String> ids = new ArrayList<>();
		ids.add(id);
		for (Authority authority : authorities) {
			if (authority.getPid().equals(id)) {
				ids.addAll(getCascadeId(authority.getId(), authorities));
			}
		}
		return ids;
	}
}
